package com.lzz.bottomencapsulation.utils;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;

import com.lzz.bottomencapsulation.R;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;


/**
 * 权限获取
 */
public class PermissionUtil {

    private static final String TAG = PermissionUtil.class.getSimpleName();
    /**
     * 获取单个权限  标识
     */
    public static final int CODE_PHONE = 1;
    public static final int CODE_STORAGE_READ  =  2;
    public static final int CODE_STORAGE_WRITE=3;
    public static final int CODE_CAMERA = 4;
    public static final int CODE_MICROPHONE= 5;
    public static final int CODE_ACCESS_FINE_LOCATION =6;
    public static final int CODE_READ_CONTACTS =7;
    public static final int CODE_CALL_PHONE =8;
    public static final int CODE_DOWLODE_APK=9;

    /**
     * 权限全部授予
     */
    public static final int CODE_MULTI_PERMISSION = 100;
    /**
     * 取消权限授予
     */
    public static final int CODE_CANCLE = -100;

    public static final String PERMISSION_PHONE = Manifest.permission.READ_PHONE_STATE;//获取设备状态
    public static final String PERMISSION_STORAGE_READ = Manifest.permission.READ_EXTERNAL_STORAGE;//写入外部存储
    public static final String PERMISSION_STORAGE_WRITE = Manifest.permission.WRITE_EXTERNAL_STORAGE;//写入外部存储
    public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;//相机
    public static final String PERMISSION_MICROPHONE = Manifest.permission.RECORD_AUDIO;//麦克风
    public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION ;//网络定位
    public static final String PERMISSION_READ_CONTACTS = Manifest.permission.READ_CONTACTS;//获取联系人
    public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE;//拨打电话
    /**
     * 权限获取数组
     */
    private static final String[] pushLivePermission = {
            PERMISSION_PHONE,
            PERMISSION_STORAGE_READ,
            PERMISSION_STORAGE_WRITE,
            PERMISSION_CAMERA,
            PERMISSION_MICROPHONE,
            PERMISSION_ACCESS_FINE_LOCATION,
            PERMISSION_READ_CONTACTS,
            PERMISSION_CALL_PHONE,
            PERMISSION_STORAGE_WRITE
    };

    public static final String[] homePermission = {
            PERMISSION_STORAGE_READ,
//            ,
            PERMISSION_STORAGE_WRITE
    };
    public static String[] waterCameraPermission= {
            PERMISSION_CAMERA
    };
    public static String[] RECORD_AUDIO_GROUP = {
            PERMISSION_MICROPHONE,PERMISSION_STORAGE_WRITE
    };

    public static String[] location= {
            PERMISSION_ACCESS_FINE_LOCATION
    };


    /**
     * 获取权限结果回调
     */
    public interface PermissionGrant {
        void onPermissionGranted(int requestCode);
    }

    /**
     * 获取单个权限
     * @param o
     * @param requestCode
     * @param permissionGrant
     */
    public static void requestPermission( Object o, int requestCode, PermissionGrant permissionGrant) {
        if (o == null) {
            return;
        }

        if (!(o instanceof Activity)&&!(o instanceof Fragment)) return;

        Context context;

        if (o instanceof Activity)
            context= (Context) o;
        else
            context=((Fragment) o).getContext();

        Log.i(TAG, "获取权限:" + requestCode);

        if ((requestCode-1) < 0 || (requestCode-1) >= pushLivePermission.length) {
            Log.w(TAG, "获取权限code不在权限列表中:" + requestCode);
            return;
        }
        String requestPermission = pushLivePermission[requestCode-1];
        //6.0以下的手机，ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED
        if (Build.VERSION.SDK_INT < 23) {
            permissionGrant.onPermissionGranted(requestCode);
            return;
        }
        //用户关闭了你申请的权限，ActivityCompat.checkSelfPermission(),会导致程序崩溃
        int checkSelfPermission;
        try {
            //权限是否授予
            checkSelfPermission = ActivityCompat.checkSelfPermission(context, requestPermission);
        } catch (RuntimeException e) {
            Log.e(TAG, "获取权限是否授予-RuntimeException-"+requestPermission.toString()+":" + e.getMessage());
//            打开设置权限页面
            openSettingActivity(o,context.getResources().getString(R.string.OPEN_PERMISSION),permissionGrant);
            return;
        }

        if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
            Log.i(TAG, "权限未授予"+requestPermission.toString());
////            是否已经禁止弹窗不再询问
//            boolean shouldShowRequestPermission=shouldShowRequestPermissionRationale(o,requestPermission);
//
//            if (!shouldShowRequestPermission) {
//                Log.i(TAG, "禁止系统权限获取弹窗显示"+requestPermission.toString());
//                shouldShowRationale(o, requestCode, requestPermission, permissionGrant);
//            } else {
////                获取权限
//                Log.d(TAG, "获取权限"+requestPermission.toString());
            requestPermissions(o,requestCode,new String[]{requestPermission});
//            }
        } else {
//            已获取
            Log.d(TAG, "权限已获取"+requestPermission.toString());
            permissionGrant.onPermissionGranted(requestCode);
        }
    }


    /**
     * 一次申请多个权限
     */
    public static void requestMultiPermissions(final Object object,String[] pushLivePermissions, final PermissionGrant
            grant) {
        Context context;

        if (object instanceof Activity)
            context= (Context) object;
        else
            context=((Fragment) object).getContext();

        //   未授予， 禁止显示弹窗的权限
        final List<String> permissionsList = getNoGrantedPermission(context,pushLivePermissions, false);
        //   未授予
        final List<String> shouldRationalePermissionsList = getNoGrantedPermission(context,pushLivePermissions, true);

        if (permissionsList == null || shouldRationalePermissionsList == null) {
//            出现了  异常情况
            return;
        }

        if (permissionsList.size() > 0) {

            requestPermissions(object,CODE_MULTI_PERMISSION,permissionsList.toArray(new
                    String[permissionsList.size()]));

        } else if (shouldRationalePermissionsList.size() > 0) {
            showMessageOKCancel(context, context.getResources().getString(R.string
                    .notPermission), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    requestPermissions(object,CODE_MULTI_PERMISSION,shouldRationalePermissionsList
                            .toArray(new String[shouldRationalePermissionsList.size()]));
                }
            }, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //                            取消授予权限
                    grant.onPermissionGranted(CODE_CANCLE);
                }
            });
        } else {
            //            权限全部授予
            grant.onPermissionGranted(CODE_MULTI_PERMISSION);
        }
    }

    /**
     * 请求回调
     */
    /**请求回调
     * @param object
     * @param requestCode  Need consistent with requestPermission
     * @param permissions
     * @param grantResults
     */
    public static void requestPermissionsResult(final Object object, final int requestCode,
                                                @NonNull String[] permissions, @NonNull int[]
                                                        grantResults, PermissionGrant
                                                        permissionGrant) {
        if (object == null) {
            return;
        }
        Activity activity;
        if (object instanceof Fragment){
            activity=((Fragment) object).getActivity();
        }else {
            activity= (Activity) object;
        }

        if (requestCode == CODE_MULTI_PERMISSION) {
//            获取多个权限处理
            requestMultiResult(activity,object, permissions, grantResults, permissionGrant);
            return;
        }
        if (requestCode < 0 ) {
            return;
        }

        if (permissions.length!=1&&requestCode >= pushLivePermission.length){
            return;
        }

        if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            permissionGrant.onPermissionGranted(requestCode);
        }else  if (requestCode==CODE_DOWLODE_APK&&grantResults.length == 1 &&grantResults[0] != PackageManager.PERMISSION_GRANTED){
            permissionGrant.onPermissionGranted(-requestCode);
        }else {
            if (!isSoftShowing(activity)) {
                shouldShowRationale(object, requestCode, permissionGrant);
            }else {
                permissionGrant.onPermissionGranted(-requestCode);
            }
        }
    }

    /**
     * 批量权限获取系统回调处理
     * @param object
     * @param permissions
     * @param grantResults
     * @param permissionGrant
     */
    private static void requestMultiResult(Activity activity,Object object, String[] permissions, int[]
            grantResults, PermissionGrant permissionGrant) {

        if (object== null) {
            return;
        }
        Log.d(TAG, "获取权限系统回调:" + permissions.length);
        Map<String, Integer> perms = new HashMap<>();//全部获取的权限

        ArrayList<String> notGranted = new ArrayList<>();//未授予的权限
        for (int i = 0; i < permissions.length; i++) {
            Log.d(TAG, "permissions: [i]:" + i + ", permissions[i]" + permissions[i] + "," +
                    "grantResults[i]:" + grantResults[i]);
            perms.put(permissions[i], grantResults[i]);
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                notGranted.add(permissions[i]);
            }
        }

        if (notGranted.size() == 0) {
            //            权限获取成功
            permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION);
        } else {
//
            if (!isSoftShowing(activity)){
                shouldShowRationale(object, CODE_MULTI_PERMISSION, permissionGrant);
            }else {
                permissionGrant.onPermissionGranted(CODE_CANCLE);
            }
        }

    }

    /**
     * 调用系统获取权限
     * @param object
     * @param requestCode
     * @param requestPermission
     */
    private static void requestPermissions(final Object object, final int requestCode, final
    String[] requestPermission){
        if (object instanceof Activity){
            ActivityCompat.requestPermissions((Activity) object, requestPermission,
                    requestCode);
        }else {
            ((Fragment)object).requestPermissions( requestPermission,
                    requestCode);
        }
    }

    /**
     * 判断权限弹窗是否禁止询问
     * @param object
     * @param requestPermission
     * @return
     */
    private static boolean shouldShowRequestPermissionRationale(Object object,String requestPermission){
        if (object instanceof Activity){
            return ActivityCompat.shouldShowRequestPermissionRationale((Activity) object, requestPermission);
        }else {
            return ActivityCompat.shouldShowRequestPermissionRationale(((Fragment)object).getActivity(), requestPermission);
        }

    }

    /**
     * 确认、取消弹窗
     * @param context
     * @param message
     * @param okListener
     * @param noListener
     */

    private static void showMessageOKCancel(final Context context, String message,
                                            DialogInterface.OnClickListener okListener,
                                            DialogInterface.OnClickListener noListener) {

        AlertDialog alertDialog  = new AlertDialog.Builder(context,R.style.Dialog2).setMessage(message)
                .setPositiveButton(context.getResources().getString(R.string.confirm),
                        okListener).setNegativeButton(context.getResources().getString(R.string
                        .cancel), noListener).create();
        alertDialog.setCanceledOnTouchOutside(false);
        alertDialog.setCancelable(false);
        alertDialog.show();
        Log.e("弹出框", "弹出框");

    }

    /**
     * 提示用户权限很重要，确认打开设置页
     * @param o
     * @param message
     * @param permissionGrant
     */
    private static void openSettingActivity(final Object o, String message, final
    PermissionGrant permissionGrant) {
        Context context=null;
        if (o instanceof Activity){
            context= (Context) o;
        }else if (o instanceof Fragment){
            context=((Fragment) o).getContext();
        }
        showMessageOKCancel(context, message, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                openSetting(o);
            }
        }, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                permissionGrant.onPermissionGranted(CODE_CANCLE);
            }
        });
    }

    /**
     * 开启设置页
     * @param o
     */
    private static void openSetting(Object o) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = null;
        if (o instanceof Activity){
            uri=Uri.fromParts("package", ((Activity)o).getPackageName(), null);
            intent.setData(uri);
            ((Activity)o).startActivity(intent);
        }else if (o instanceof Fragment){
            uri=Uri.fromParts("package", ((Fragment) o).getActivity().getPackageName(), null);
            intent.setData(uri);
            ((Fragment)o).getActivity().startActivity(intent);
        }
    }

    /**
     * 系统已禁止权限弹窗显示，给出弹窗
     * @param object
     * @param requestCode
     * @param permissionGrant
     */
    private static void shouldShowRationale(final Object object, final int requestCode, final PermissionGrant permissionGrant) {
        final Context context;
        if (object instanceof Activity){
            context= (Context) object;
        }else {
            context= ((Fragment)object).getContext();
        }
        String messge="";
        if (requestCode==CODE_MULTI_PERMISSION){
            messge=context.getResources().getString(R.string.OPEN_PERMISSION);
        }else {
            String[] permissionsHint=context.getResources().getStringArray(R.array.permissions);
            messge=permissionsHint[requestCode-1];
        }
        showMessageOKCancel(context,messge, new DialogInterface
                .OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                openSetting(object);
                SPUtils.put(context,"show_message_ok_cancel",false);
            }
        }, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (requestCode==CODE_MULTI_PERMISSION){
                    permissionGrant.onPermissionGranted(CODE_CANCLE);
                }else {
                    permissionGrant.onPermissionGranted(-requestCode);
                }
                SPUtils.put(context,"show_message_ok_cancel",false);
            }
        });
    }


    /**
     * 获得未授予的权限
     *
     * @param object
     * @param isShouldRationale true: 未禁止弹窗,
     *                          false:禁止弹窗
     * @return
     */
    public static ArrayList<String> getNoGrantedPermission(Object object, String[] pushLivePermissions, boolean
            isShouldRationale) {
        ArrayList<String> permissions = new ArrayList<>();
        Context context;
        if (object instanceof Fragment){
            context=((Fragment) object).getContext();
        }else {
            context= (Context) object;
        }
        for (int i = 0; i < pushLivePermissions.length; i++) {
            String requestPermission = pushLivePermissions[i];
            if (Build.VERSION.SDK_INT < 23) {
                if (PermissionChecker.checkSelfPermission(context,requestPermission)!=PackageManager.PERMISSION_GRANTED) {
//                未授予的权限
                    permissions.add(requestPermission);
                }
            }else {
                int checkSelfPermission = -1;
                try {
                    checkSelfPermission=PermissionChecker.checkSelfPermission(context,requestPermission);
                } catch (RuntimeException e) {
                    //                获取权限情况出现异常
                    TUtils.showShort(context, context.getResources().getString(R.string
                            .notPermission));
                    Log.e(TAG, "获取权限是否授予情况出现异常RuntimeException:" + e.getMessage());
                    return null;
                }
                if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
//                    是否禁止显示权限获取窗口
                    if (shouldShowRequestPermissionRationale(context, requestPermission)) {
//                        没有禁止
                        if (isShouldRationale) {
                            permissions.add(requestPermission);
                        }
                    } else {
//
                        if (!isShouldRationale) {
                            permissions.add(requestPermission);
                        }
                    }
                }
            }
        }
        return permissions;
    }



    private static boolean isSoftShowing(Activity activity) {
        boolean ifshow= (boolean) SPUtils.get(activity, "show_message_ok_cancel", false);
        SPUtils.put(activity,"show_message_ok_cancel",true);
        return ifshow;
    }


    /**
     * 判断权限集合
     * permissions 权限数组
     * return true-表示没有改权限 false-表示权限已开启
     */
    public static boolean lacksPermissions(Context mContexts,String[] permissionsREAD) {
        for (String permission : permissionsREAD) {
            if (lacksPermission(mContexts,permission)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否缺少权限
     */
    public static boolean lacksPermission(Context mContexts, String permission) {
        return ContextCompat.checkSelfPermission(mContexts, permission) ==
                PackageManager.PERMISSION_DENIED;
    }

    /**
     * 通知权限是否授予
     * @param context
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static boolean isNotificationEnabled(Context context) {

        String CHECK_OP_NO_THROW = "checkOpNoThrow";
        String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        ApplicationInfo appInfo = context.getApplicationInfo();
        String pkg = context.getApplicationContext().getPackageName();
        int uid = appInfo.uid;

        Class appOpsClass = null;
        /* Context.APP_OPS_MANAGER */
        try {
            appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
                    String.class);
            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);

            int value = (Integer) opPostNotificationValue.get(Integer.class);
            return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
